using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Pavilion;

namespace Pavilion.Control
{
    abstract public class Control : IChain<Control>
    {
        #region //////////////////////////////////////////////Attributes//////////////////////////////////////////////

        private bool enabled, visible, isActive;
        private Color backgroundColor, outlineColor;
        private Rectangle areaBounds;
        private ChainControl<Control> chainControl;
        
        private InputComponent inputComponent;
        private MoveComponent moveComponent;
        private NotifiableCollection<Control> collectionComponent;

        private event EventHandler resize, reposition;
        public event Action<bool> IsActiveChanged;

        #endregion

        #region ////////////////////////////////////////////Initialization////////////////////////////////////////////

        public Control()
        {
            isActive = enabled = visible = true;
            BackgroundColor = Color.White;
            outlineColor = Color.Black;
            areaBounds = new Rectangle(0, 0, 200, 200);
            collectionComponent = new NotifiableCollection<Control>();
            chainControl = new ChainControl<Control>(_Collection, this);
            inputComponent = new InputComponent(this);

            collectionComponent.Added += new Action<Control, int>(Collection_ControlAdded);

            Input.OuterClick += new Action<MouseCursor>(Input_OuterClick);
            Input.MousePress += new MouseObjectHandler(Input_MousePress);
        }

        public virtual void Dispose()
        {
            collectionComponent.Added -= new Action<Control, int>(Collection_ControlAdded);
            Input.OuterClick -= new Action<MouseCursor>(Input_OuterClick);
            Input.MousePress -= new MouseObjectHandler(Input_MousePress);

            Input.Dispose();

            foreach (Control control in _Collection)
                control.Dispose();

            _Collection.Clear();
        }

        #endregion

        #region ////////////////////////////////////////////////Methods///////////////////////////////////////////////

        public virtual void Draw()
        {
            if (!Visible && collectionComponent != null)
                return;

            for (int i = 0; i < _Collection.Count; i++)
                _Collection[i].Draw();
        }

        /// <summary>
        /// Removes itself from the parent control.
        /// </summary>
        public void DetachFromParent()
        {
            if (Parent != null)
                Parent._Collection.Remove(this);
        }

        private void SetIsActive(bool value)
        {
            for (int i = 0; i < _Collection.Count; i++)
                _Collection[i].SetIsActive(value);

            if (isActive == value)
                return;

            isActive = value;
            OnIsActiveChanged();
        }

        #endregion

        #region ////////////////////////////////////////General Gets and Sets/////////////////////////////////////////

        /// <summary>
        /// Gets the Input Component of this control that allows for registration of input functionality.
        /// </summary>
        public InputComponent Input
        {
            get { return inputComponent; }
        }

        /// <summary>
        /// Gets the Move Component of this control that allows for registration of moving and dropping functionality.
        /// </summary>
        public MoveComponent Move
        {
            get
            {
                if (moveComponent == null)
                    moveComponent = new MoveComponent(this);

                return moveComponent;
            }
        }

        /// <summary>
        /// Gets the Collection Component of this control that allows for adding and removing of controls.
        /// </summary>
        protected NotifiableCollection<Control> _Collection
        {
            get { return collectionComponent; }
        }


        /// <summary>
        /// Gets the ChainControl of this chain item.
        /// </summary>
        public ChainControl<Control> ChainControl
        {
            get { return chainControl; }
        }

        /// <summary>
        /// Gets or Sets whether the functionality of this control is enabled.
        /// </summary>
        public virtual bool Enabled
        {
            get { return enabled; }
            set
            {
                if (value != enabled)
                {
                    enabled = value;
                    //SetIsActive(visible && enabled);
                }
            }
        }

        /// <summary>
        /// Gets or sets the visibility of this control.
        /// </summary>
        public virtual bool Visible
        {
            get { return visible; }
            set
            {
                if (value != visible)
                {
                    visible = value;
                    //SetIsActive(visible && enabled);
                }
            }
        }

        /// <summary>
        /// Gets whether the control is currently active.
        /// </summary>
        public bool IsActive
        {
            get { return isActive; }
        }

        /// <summary>
        /// Gets the parent of this control.
        /// </summary>
        public Control Parent
        {
            get { return (Control)ChainControl.Parent; }
        }

        /// <summary>
        /// Gets or sets the background color of this control.
        /// </summary>
        public Color BackgroundColor
        {
            get { return backgroundColor; }
            set { backgroundColor = value; }
        }

        /// <summary>
        /// Gets or sets the outline color of this control.
        /// </summary>
        public Color OutlineColor
        {
            get { return outlineColor; }
            set { outlineColor = value; }
        }

        /// <summary>
        /// Gets or sets the location and size of this control.
        /// </summary>
        public Rectangle AreaBounds
        {
            get { return areaBounds; }
            set
            {
                Rectangle previousBounds = areaBounds;
                areaBounds = value;

                if (previousBounds.Width != value.Width || previousBounds.Height != value.Height)
                    OnResize();

                if (previousBounds.X != value.X || previousBounds.Y != value.Y)
                    OnReposition();
            }
        }

        /// <summary>
        /// Gets the position of the Control relative to the screen.
        /// </summary>
        public Rectangle ScreenBounds
        {
            get
            {
                if (Parent == null)
                    return AreaBounds;

                Rectangle screenPosition = Parent.ScreenBounds;

                screenPosition.X += AreaBounds.X;
                screenPosition.Y += AreaBounds.Y;
                screenPosition.Width = AreaBounds.Width;
                screenPosition.Height = AreaBounds.Height;

                return screenPosition; 
            }
        }

        /// <summary>
        /// Gets or sets the position of this control.
        /// </summary>
        public virtual Point Position
        {
            get { return new Point(AreaBounds.X, AreaBounds.Y); }
            set { AreaBounds = new Rectangle(value.X, value.Y, AreaBounds.Width, AreaBounds.Height); }
        }

        /// <summary>
        /// Gets the control that is visible, enabled, and is the outer most top of all the controls
        /// based on the location of the mouse cursor.
        /// </summary>
        public Control OuterMostControl(MouseCursor mouseCursor)
        {
            for (int i = _Collection.Count - 1; i >= 0; i--)
            {
                if (_Collection[i].Visible && _Collection[i].Enabled)
                {
                    if (mouseCursor.checkBounds(_Collection[i].ScreenBounds))
                        return _Collection[i];
                }
            }
            return null;
        }

        #endregion

        #region /////////////////////////////////////////Event Gets and Sets//////////////////////////////////////////

        public virtual event EventHandler Resize
        {
            add { resize += value; }
            remove { resize -= value; }
        }

        public virtual event EventHandler Reposition
        {
            add { reposition += value; }
            remove { reposition -= value; }
        }

        #endregion

        #region ////////////////////////////////////////////////Events////////////////////////////////////////////////

        protected virtual void OnResize()
        {
            if (resize != null)
                resize(this, EventArgs.Empty);
        }

        protected virtual void OnReposition()
        {
            if (reposition != null)
                reposition(this, EventArgs.Empty);
        }

        private void OnIsActiveChanged()
        {
            if (IsActiveChanged != null)
                IsActiveChanged(IsActive);
        }

        private void Collection_ControlAdded(Control item, int index)
        {
            item.SetIsActive(isActive);
        }

        private void Input_MousePress(object sender, MouseCursor mouseCursor)
        {
            SetIsActive(true);
        }

        private void Input_OuterClick(MouseCursor mouseCursor)
        {
            SetIsActive(false);
        }

        #endregion
    }
}
